import CTMapOl from '@ct/ct_map_ol'
import { getLength, getArea } from 'ol/sphere.js'
import MVT from 'ol/format/MVT.js'
import VectorTile from 'ol/source/VectorTile.js'
import axios from 'axios'
/**
 * 获取线的长度
 * @param coordArr 坐标数组
 * @return {*} 距离家和数组 单位千米
 */
export function getOlLineStringLength(coordArr) {
  let lengthArr = []

  for (let i = 0; i < coordArr.length - 1; i++) {
    let line = new CTMapOl.geom.LineString([coordArr[i], coordArr[i + 1]])
    let length = getLength(line, {
      projection: 'EPSG:3857'
    })
    lengthArr.push(length)
  }

  let sumArr = lengthArr.reduce(
    (arr, num) => {
      let lastVal = arr[arr.length - 1]
      arr.push(lastVal + num)
      return arr
    },
    [0]
  )

  sumArr = sumArr.map(item => {
    let tmpVal = (item / 1000).toFixed(2)
    return parseFloat(tmpVal)
  })
  return sumArr
}

/**
 * 获取面的面积
 * @param coordArr 坐标数组
 * @return {*} 距离家和数组 单位平方米
 */
export function getOlPolygonArea(coordArr) {
  let polygon = new CTMapOl.geom.Polygon(coordArr)
  let area = getArea(polygon, {
    projection: 'EPSG:3857'
  })
  return parseFloat(area.toFixed(2))
}

/**
 * 测量图层
 * 根据经纬度绘制图层和overlay
 */
export class measureOverlayClass {
  constructor(_map) {
    this.map = _map
    const drawStyle = new CTMapOl.style.Style({
        fill: new CTMapOl.style.Fill({
          color: "rgba(237, 81, 88, 1)"
        }),
        stroke: new CTMapOl.style.Stroke({
          color: "rgba(237, 81, 88, 0.30)",
          width: 2
        })
      });
    this.vectorSource = new CTMapOl.source.Vector({ wrapX: false });
    this.drawVectorLayer = new CTMapOl.layer.Vector({
      source: this.vectorSource,
      zIndex: Infinity,
      style: drawStyle
    })
    this.map.addLayer(this.drawVectorLayer)
    this.overLayerObj = {}
    this.glOverlayObj = {}
    this.featuresObj = {}
  }

  get(key) {
    return this[key]
  }

  drawLine(path, key) {
    // 设置图层的样式
    let style = new CTMapOl.style.Style({
      fill: new CTMapOl.style.Fill({
        color: "rgba(237, 81, 88, 1)"
      }),
      stroke: new CTMapOl.style.Stroke({
        color: "rgba(237, 81, 88, 1)",
        width: 2
      }),
    });
    let stylePoint = new CTMapOl.style.Style({
      image: new CTMapOl.style.Circle({
        radius: 4,
        fill: new CTMapOl.style.Fill({
          color: "rgba(255, 255, 255, 1)",
        }),
        stroke: new CTMapOl.style.Stroke({
          color: "rgba(237, 81, 88, 1)",
          width: 2
        })
      }),
      geometry: function (feature) {
        const coordinates = feature.getGeometry().getCoordinates();
        console.log(coordinates);
        return new CTMapOl.geom.MultiPoint(coordinates);
      },
    });
    let styles = [style,stylePoint];
    this.drawVectorLayer.setStyle(styles);
    if(this.featuresObj[key]){
      this.vectorSource.removeFeature(this.featuresObj[key][0]);
    }
    let newPath = []
    path.forEach((item) => {
      let lnglat = CTMapOl.extend.formatLayer.transCooordinateToOpenlayer(item)
      newPath.push(lnglat)
    })
    let disArr = getOlLineStringLength(newPath)
    this.glOverlayObj[key] = []
    this.featuresObj[key] = []
    this.overLayerObj[key] = []
    disArr.forEach((item, index) => {
      this.glOverlayObj[key].push({
        key: index,
        pos: newPath[index],
        value: item ? item + '千米' : '起点'
      })
    })
    this.drawLayerAddFeature(key, newPath, 'LineString')
  }

  drawArea(path, key,isRed) {
    let style;
    let stylePoint;
    if (isRed){
      // 设置图层的样式
      style = new CTMapOl.style.Style({
        fill: new CTMapOl.style.Fill({
          color: "rgba(237, 81, 88, 0.30)"
        }),
        stroke: new CTMapOl.style.Stroke({
          color: "rgba(237, 81, 88, 1)",
          width: 2
        })
      });
      stylePoint = new CTMapOl.style.Style({
        image: new CTMapOl.style.Circle({
          radius: 0,
          fill: new CTMapOl.style.Fill({
            color: "rgba(255, 255, 255, 1)",
          }),
          stroke: new CTMapOl.style.Stroke({
            color: "rgba(237, 81, 88, 1)",
            width: 2
          })
        }),
        geometry: function (feature) {
          const coordinates = feature.getGeometry().getCoordinates()[0];
          console.log(coordinates);
          return new CTMapOl.geom.MultiPoint(coordinates);
        },
      });
    }else{
      // 设置图层的样式
      style = new CTMapOl.style.Style({
        fill: new CTMapOl.style.Fill({
          color: "rgba(237, 81, 88, 0.30)"
        }),
        stroke: new CTMapOl.style.Stroke({
          color: "rgba(237, 81, 88, 1)",
          width: 2
        })
      });
      stylePoint = new CTMapOl.style.Style({
        image: new CTMapOl.style.Circle({
          radius: 4,
          fill: new CTMapOl.style.Fill({
            color: "rgba(255, 255, 255, 1)",
          }),
          stroke: new CTMapOl.style.Stroke({
            color: "rgba(237, 81, 88, 1)",
            width: 2
          })
        }),
        geometry: function (feature) {
          const coordinates = feature.getGeometry().getCoordinates()[0];
          console.log(coordinates);
          return new CTMapOl.geom.MultiPoint(coordinates);
        },
      });
    }
    let styles = [style,stylePoint];
    this.drawVectorLayer.setStyle(styles);
    let newPath = [[]]
    path[0].forEach((item) => {
      let lnglat = CTMapOl.extend.formatLayer.transCooordinateToOpenlayer(item)
      newPath[0].push(lnglat)
    })
    let area = getOlPolygonArea(newPath)
    let unit = '平方米'
    area = area.toFixed(2)
    // if (area > 1000000) {
    //   unit = '平方公里'
    //   area = (area / 1000000).toFixed(2)
    // }
    this.featuresObj[key] = []
    this.glOverlayObj[key] = [
      {
        key: 0,
        pos: newPath[0][0],
        value: '总面积：' + area + unit
      }
    ]
    this.overLayerObj[key] = []
    this.drawLayerAddFeature(key, newPath, 'Polygon')
  }

  drawLayerAddFeature(key, coordinates, type = 'Polygon') {
    let feature = null
    if (!this.featuresObj[key]) {
      this.featuresObj[key] = []
    }
    if (type === 'Polygon') {
      const polygonFeature = new CTMapOl.geom.Polygon(coordinates)
      feature = new CTMapOl.Feature({
        geometry: polygonFeature
      })
    } else {
      const polygonFeature = new CTMapOl.geom.LineString(coordinates)
      feature = new CTMapOl.Feature({ geometry: polygonFeature })
    }
    this.featuresObj[key].push(feature)
    this.vectorSource.addFeature(feature)
  }

  addOverLay(headerId, key) {
    if (!this.glOverlayObj[key] || this.glOverlayObj[key].length === 0) {
      return
    }
    this.glOverlayObj[key].forEach(item => {
      let id = `${headerId + item.key}`
      let overlay = new CTMapOl.Overlay({
        position: item.pos,
        positioning: 'center-center',
        offset: [0, -20],
        element: document.getElementById(id)
      })
      this.overLayerObj[key].push(overlay)
      this.map.addOverlay(overlay)
    })
  }

  removeByKey(key) {
    if (this.overLayerObj[key] && this.overLayerObj[key].length > 0) {
      this.overLayerObj[key].forEach(item => {
        this.map.removeOverlay(item)
      })
    }
    if (this.featuresObj[key] && this.featuresObj[key].length > 0) {
      this.featuresObj[key].forEach(item => {
        this.vectorSource.removeFeature(item)
      })
    }
    Reflect.deleteProperty(this.featuresObj, key)
    Reflect.deleteProperty(this.overLayerObj, key)
    Reflect.deleteProperty(this.glOverlayObj, key)
  }

  remove() {
    for (let key in this.overLayerObj) {
      if (this.overLayerObj[key] && this.overLayerObj[key].length > 0) {
        this.overLayerObj[key].forEach(item => {
          this.map.removeOverlay(item)
        })
      }
    }
    for (let key in this.featuresObj) {
      if (this.featuresObj[key] && this.featuresObj[key].length > 0) {
        this.featuresObj[key].forEach(item => {
          this.vectorSource.removeFeature(item)
        })
      }
    }
    this.overLayerObj = {}
    this.glOverlayObj = {}
    this.featuresObj = {}
  }
}

/**
 * 图斑选择图层
 */
export class layerTreeClass {
  constructor(_map, _selectFn, _changeFn) {
    this.map = _map
    this.selection = {}
    this.vectorTileSource = null
    this.vectorTileLayer = null
    this.selectPolygonLayer = null
    this.singleClickFn = this.selectFeature.bind(this)
    this.selectFn = _selectFn
    this.changeFn = _changeFn;
    this.baseUrl = ''
    this.gridNames = [
      'EPSG:900913:0',
      'EPSG:900913:1',
      'EPSG:900913:2',
      'EPSG:900913:3',
      'EPSG:900913:4',
      'EPSG:900913:5',
      'EPSG:900913:6',
      'EPSG:900913:7',
      'EPSG:900913:8',
      'EPSG:900913:9',
      'EPSG:900913:10',
      'EPSG:900913:11',
      'EPSG:900913:12',
      'EPSG:900913:13',
      'EPSG:900913:14',
      'EPSG:900913:15',
      'EPSG:900913:16',
      'EPSG:900913:17',
      'EPSG:900913:18',
      'EPSG:900913:19',
      'EPSG:900913:20',
      'EPSG:900913:21',
      'EPSG:900913:22',
      'EPSG:900913:23',
      'EPSG:900913:24',
      'EPSG:900913:25',
      'EPSG:900913:26',
      'EPSG:900913:27',
      'EPSG:900913:28',
      'EPSG:900913:29',
      'EPSG:900913:30'
    ]
    this.selectColor = 'rgba(237, 81, 88, 0.30)'
    this.selectBorderColor = 'rgba(237, 81, 88, 1)'
    this.defaultBorderColor = 'rgba(225, 207, 32, 0.8)'
    this.defaultColor = 'rgba(225, 207, 32, 0.4)'
    this.layerName = ''
    this.layerNamespace = ''
  }

  set(key, value) {
    this[key] = value
  }

  setBaseData(url, name, layerNamespace) {
    this.baseUrl = url
    this.layerName = name
    this.layerNamespace = layerNamespace
    this.initVectorLayer()
  }

  constructSource() {
    const _this = this

    let projection = new CTMapOl.proj.Projection({
      code: 'EPSG:900913',
      units: 'm',
      axisOrientation: 'neu'
    })
    const resolutions = [
      156543.03390625, 78271.516953125, 39135.7584765625, 19567.87923828125, 9783.939619140625, 4891.9698095703125,
      2445.9849047851562, 1222.9924523925781, 611.4962261962891, 305.74811309814453, 152.87405654907226, 76.43702827453613,
      38.218514137268066, 19.109257068634033, 9.554628534317017, 4.777314267158508, 2.388657133579254, 1.194328566789627,
      0.5971642833948135, 0.29858214169740677, 0.14929107084870338, 0.07464553542435169, 0.037322767712175846,
      0.018661383856087923, 0.009330691928043961, 0.004665345964021981, 0.0023326729820109904, 0.0011663364910054952,
      5.831682455027476e-4, 2.915841227513738e-4, 1.457920613756869e-4
    ]

    const source = new VectorTile({
      url: this.baseUrl,
      format: new MVT({}),
      renderMode: 'vector',
      projection: projection,
      tileGrid: new CTMapOl.tilegrid.WMTS({
        tileSize: [256, 256],
        extent: [-2.003750834e7, -2.003750834e7, 2.003750834e7, 2.003750834e7],
        origin: [-2.003750834e7, 2.003750834e7],
        resolutions: resolutions,
        matrixIds: _this.gridNames
      }),
      wrapX: true
    })
    return source
  }

  selectColorFn() {
    return new CTMapOl.style.Style({
      stroke: new CTMapOl.style.Stroke({
        color: this.selectBorderColor,
        width: 2
      }),
      fill: new CTMapOl.style.Fill({
        color: this.selectColor
      }),
      image: new CTMapOl.style.Circle({
        stroke: new CTMapOl.style.Stroke({
          color: this.selectBorderColor,
          width: 2
        }),
        fill: new CTMapOl.style.Fill({
          color: this.selectColor
        }),
      })
    })
  }

  defaultColorFn() {
    return new CTMapOl.style.Style({
      stroke: new CTMapOl.style.Stroke({
        color: this.defaultBorderColor,
        width: 2
      }),
      fill: new CTMapOl.style.Fill({
        color: this.defaultColor
      }),
      image: new CTMapOl.style.Circle({
        radius: 3.5,
        stroke: new CTMapOl.style.Stroke({
          color: 'rgba(60, 62, 66, 1)',
          width: 0.5
        }),
        fill: new CTMapOl.style.Fill({
          color: 'rgba(225, 207, 32, 1)'
        }),
      })
    })
  }

  /**
   * 初始化图层
   * 初始化图层之前一定要先确保清空之前的图层。
   */
  initVectorLayer() {
    const _this = this
    this.map.on('click', this.singleClickFn);
    this.vectorTileSource = this.constructSource(this.baseUrl)
    this.vectorTileLayer = new CTMapOl.layer.VectorTile({
      source: this.vectorTileSource,
      zIndex: 999,
      renderMode: 'vector',
      style:_this.defaultColorFn()
    })

    this.map.addLayer(this.vectorTileLayer)

    this.selectPolygonLayer = new CTMapOl.layer.VectorTile({
      // map: this.map,
      renderMode: 'vector',
      source: this.vectorTileSource,
      zIndex: 9999,
      style: function (feature) {
        const properties = feature.getProperties()
        const fid = properties['BSM'] || properties['bsm']
        if ((fid in _this.selection) && _this.changeFn()) {
            return _this.selectColorFn()
        }
      }
    })
    this.map.addLayer(this.selectPolygonLayer)
  }

  selectFeature(evt) {
    this.vectorTileLayer.getFeatures(evt.pixel).then(features => {
      if (!features.length) {
        // this.selection = {}
        // this.selectPolygonLayer.changed()
        this.selectFn('', {});
        return
      }
      const feature = features[0]
      if (!feature) {
        // this.selectFn('', {})
        return
      }
      const properties = feature.getProperties()
      const fid = properties['BSM'] || properties['bsm'] || ''
      if (fid in this.selection) {
        delete this.selection[fid]
        this.selection = {}
        this.selectFn('', {})
      } else {
        this.selection = {}
        this.selection[fid] = feature
        this.selectFn(fid, properties,feature);
      }
      // this.selection[fid] = feature
      this.selectPolygonLayer.changed()
    })
  }

  setSelectFeatureById(fid) {
    this.selection = {}
    if (fid) {
      this.selection[fid] = null
    }
    this.selectPolygonLayer?.setStyle(this.selectPolygonLayer.getStyle());
    this.selectPolygonLayer?.changed();
  }

  distory() {
    if (this.selectPolygonLayer != null && this.vectorTileLayer != null && this.vectorTileSource != null) {
      this.map.removeLayer(this.vectorTileLayer)
      this.map.removeLayer(this.selectPolygonLayer)
      this.vectorTileSource = null
      this.vectorTileLayer = null
      this.selectPolygonLayer = null
    }
    if(this.singleClickFn){
      this.map.un('click', this.singleClickFn)
    }
  }
}

/**
 * 看这里点图层
 * @param {*} _map 地图实例
 * @param {*} pointStyle 点样式
 */
export class pointClass {
  constructor(_map, pointStyle) {
    this.map = _map
    this.source = new CTMapOl.source.Vector()
    this.layer = new CTMapOl.layer.Vector({
      source: this.source,
      style: pointStyle
    })
    this.map.addLayer(this.layer)
    this.pointFeature = null
  }

  addPoint(center) {
    this.removePoint()
    const point = new CTMapOl.geom.Point(center)
    this.pointFeature = new CTMapOl.Feature(point)
    this.source.addFeature(this.pointFeature)
  }

  removePoint() {
    if (this.source && this.pointFeature) {
      this.source.removeFeature(this.pointFeature)
    }
  }

  distory() {
    if (this.layer) {
      this.map.removeLayer(this.layer)
      this.source = null
      this.layer = null
      this.pointFeature = null
    }
  }
}
